using System;
using System.Collections.Generic;
using System.Text;
using System.Data.SqlClient;
using System.Data;

namespace ApplicationCore
{
    public class SecurityDescriptor
    {
        private SortedDictionary<string, List<TableRight>> rights;
        private List<string> roles;
        private bool isSqlUser;

        public SortedDictionary<string, List<TableRight>> Rights
        {
            get
            {
                return rights;
            }
        }

        public bool IsSqlUser
        {
            get { return isSqlUser; }
        }

        public SecurityDescriptor(SqlConnection con)
        {
            this.roles = new List<string>();
            this.rights = new SortedDictionary<string, List<TableRight>>();
            string u = User(con);
            isSqlUser = !u.Contains(@"\");
            QueryRoles(con, u);
            EvaluateRights(con);
        }

        private void EvaluateRights(SqlConnection con)
        {
            string sql = @"
SELECT 
	SCHEMA_NAME(o.[schema_id]) as [schema],
	o.name,
	p.[permission_name] as permission
 FROM sys.objects AS o 
 CROSS APPLY sys.fn_my_permissions(o.name, N'OBJECT') AS p
	WHERE o.[type] IN (N'U', N'V') -- tables and views
	AND subentity_name = N'' -- ignore column permissions 
 ORDER BY [schema], o.name";
            using (SqlCommand cmd = new SqlCommand(sql, con))
            {
                cmd.CommandType = CommandType.Text;

                try
                {
                    cmd.Connection.Open();
                    using (SqlDataReader r = cmd.ExecuteReader(CommandBehavior.SingleResult | CommandBehavior.CloseConnection | CommandBehavior.SequentialAccess))
                    {
                        while (r.Read())
                        {
                            string schema = r.GetString(0);
                            string table = r.GetString(1);
                            string permission = r.GetString(2);
                            AddRight(table, permission);
                        }
                    }
                }
                catch (SqlException)
                {
                    throw;
                }
                finally
                {
                    cmd.Connection.Close();
                }
            }
        }

        private void AddRight(string table, string permission)
        {
            if (!this.rights.ContainsKey(table))
                this.rights.Add(table, new List<TableRight>());

            rights[table].Add((TableRight)Enum.Parse(typeof(TableRight), permission, true));
        }

        private void QueryRoles(SqlConnection con, string user)
        {
            using (SqlCommand cmd = new SqlCommand("sp_helproleember2", con))
            {
                cmd.CommandType = CommandType.StoredProcedure;
                cmd.Parameters.Add("@user", SqlDbType.NVarChar, 128).Value = user;

                try
                {
                    cmd.Connection.Open();

                    using (SqlDataReader r = cmd.ExecuteReader())
                    {
                        while (r.Read())
                        {
                            string role = r.GetString(0);
                            this.roles.Add(role);
                        }
                    }
                }
                catch (Exception)
                {
                    throw;
                }
                finally
                {
                    cmd.Connection.Close();
                }
            }
        }

        private string User(SqlConnection con)
        {
            //return  @"MPIMP-GOLM\Gibon";
            using (SqlCommand cmd = new SqlCommand("select SYSTEM_USER", con))
            {
                cmd.CommandType = CommandType.Text;

                try
                {
                    cmd.Connection.Open();
                    object ret = cmd.ExecuteScalar();
                    if (ret != null)
                        return (string)ret;
                    else
                        return null;
                }
                finally
                {
                    cmd.Connection.Close();
                }
            }
        }

        public bool HasRight(string tableName, TableRight tabRight)
        {
            return true;
        }
    }

    public enum TableRight
    {
        Select,
        Insert,
        Update,
        Delete
    }
}
